package org.example.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import lombok.extern.slf4j.Slf4j;
import org.example.mapper.RoleMapper;
import org.example.mapper.UserMapper;
import org.example.model.table.ClassTable;
import org.example.model.table.Role;
import org.example.model.table.Score;
import org.example.model.table.User;
import org.example.model.vo.UserVo;
import org.example.service.UserService;
import org.example.util.JwtUtils;
import org.example.util.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
@Transactional(propagation = Propagation.REQUIRED)
public class UserServiceImpl implements UserService {

    private String DEFAULT_PASSWORD = "123456";
    @Autowired
    UserMapper userMapper;
    @Autowired
    RoleMapper roleMapper;

    @Override
    public Result login(UserVo paramUser) {
        MPJLambdaWrapper<User> userMPJLambdaWrapper = new MPJLambdaWrapper<>();
        userMPJLambdaWrapper.selectAs(User::getId, UserVo::getId).selectAs(User::getName, UserVo::getName).selectAs(User::getGender, UserVo::getGender).selectAs(User::getStatus, UserVo::getStatus).selectAs(User::getAccount, UserVo::getAccount).selectAs(User::getRoleId, UserVo::getRoleId).selectAs(Role::getRole, UserVo::getRole).selectAs(Role::getName, UserVo::getRoleName).selectAs(Role::getStatus, UserVo::getRoleStatus).selectAs(ClassTable::getName, UserVo::getClassName).selectAs(ClassTable::getId, UserVo::getClassId).innerJoin(Role.class, Role::getId, User::getRoleId).innerJoin(ClassTable.class, ClassTable::getId, User::getClassId).eq(User::getAccount, paramUser.getAccount()).eq(User::getPassword, paramUser.getPassword());
        UserVo userVo = userMapper.selectJoinOne(UserVo.class, userMPJLambdaWrapper);

        if (userVo != null) {
            if (userVo.getStatus() != 0 && userVo.getRoleStatus() != 0) {
                return Result.ok().data("token", JwtUtils.createToken(userVo)).data("msg", "welcome");
            } else {
                return Result.error().data("msg", "account status is disable").setCode(403);
            }
        }
        return Result.error().data("msg", "account or password error").setCode(403);
    }

    @Override
    public Result getUserById(Long id) {
        UserVo userVo = userMapper.selectJoinOne(UserVo.class, new MPJLambdaWrapper<User>().select(User::getId).selectAs(User::getName, UserVo::getName).selectAs(Role::getRole, UserVo::getRoleName).selectAs(User::getRoleId, User::getRoleId).select(Score::getMark).innerJoin(Role.class, Role::getId, User::getRoleId).innerJoin(Score.class, Score::getStudentId, User::getId).eq(User::getId, id));
        if (userVo != null) return Result.ok().data("user", userVo);
        return Result.error().data("'msg", "查无此人").setCode(404);
    }

    @Override
    public Result getPageUser(Integer page, Integer size, UserVo userVo) {
        MPJLambdaWrapper<User> wrapper = new MPJLambdaWrapper<>();
        wrapper.selectAs(User::getId, UserVo::getId)
                .selectAs(User::getName, UserVo::getName)
                .selectAs(User::getGender, UserVo::getGender)
                .selectAs(User::getStatus, UserVo::getStatus)
                .selectAs(User::getAccount, UserVo::getAccount)
                .selectAs(User::getRoleId, UserVo::getRoleId)
                .selectAs(Role::getRole, UserVo::getRole)
                .selectAs(Role::getName, UserVo::getRoleName)
                .selectAs(Role::getStatus, UserVo::getRoleStatus)
                .selectAs(ClassTable::getId, UserVo::getClassId)
                .selectAs(ClassTable::getName, UserVo::getClassName)
                .leftJoin(Role.class, Role::getId, User::getRoleId)
                .leftJoin(ClassTable.class, ClassTable::getId, User::getClassId);
        if (userVo.getId()!=null){
            // 精确查找，忽略其它参数
            wrapper.eq(userVo.getId() != null, User::getId, userVo.getId());
        }else {
            // 组合查询
            wrapper.eq(userVo.getStatus()!=null, User::getStatus, userVo.getStatus())
                    .eq(userVo.getRoleId()!=null, Role::getId, userVo.getRoleId())
                    .eq(userVo.getClassId()!=null, ClassTable::getId, userVo.getClassId())
                    .eq(StringUtils.isNotBlank(userVo.getGender()), User::getGender, userVo.getGender())
                    .like(StringUtils.isNotBlank(userVo.getName()),User::getName, userVo.getName())
                    .like(StringUtils.isNotBlank(userVo.getAccount()), User::getAccount, userVo.getAccount());
        }
        IPage<UserVo> userVoIPage = userMapper.selectJoinPage(new Page<UserVo>(page, size), UserVo.class, wrapper);
        if (userVoIPage != null && userVoIPage.getRecords().size() > 0){
            return Result.ok().data("userList", userVoIPage);
        }
        return Result.ok().data("msg", "暂无数据").setCode(404);
    }

    @Override
    public Result getUserListByIds(List<Long> ids) {
        ArrayList<UserVo> list = new ArrayList<>();
        for (Long id : ids) {
            MPJLambdaWrapper<User> wrapper = new MPJLambdaWrapper<>();
            UserVo userVo = userMapper.selectJoinOne(UserVo.class, wrapper.select(User::getId).selectAs(User::getName, UserVo::getName).selectAs(Role::getRole, UserVo::getRole).selectAs(User::getRoleId, User::getRoleId).select(Score::getMark).innerJoin(Role.class, Role::getId, User::getRoleId).innerJoin(Score.class, Score::getStudentId, User::getId).eq(User::getId, id));
            if (userVo != null) list.add(userVo);
        }
        if (list.size() > 0) return Result.ok().data("users", list).data("msg", "查询成功");
        return Result.error().data("'msg", "查无此人").setCode(404);
    }


    @Override
    public Result add(String token, UserVo userVo) {
        UserVo userInfo = JwtUtils.toObj(token, UserVo.class);
        LambdaQueryWrapper<User> userQueryWrapper = new LambdaQueryWrapper<>();
        userQueryWrapper.eq(User::getAccount, userInfo.getAccount());
        // 判断token封装的account是否存在
        User tokenUser = userMapper.selectOne(userQueryWrapper);
        if (tokenUser.getAccount() != null) {
            // 判断数据库是否已有账号,account字段具有唯一约束
            LambdaQueryWrapper<User> newUserQueryWrapper = new LambdaQueryWrapper<>();
            newUserQueryWrapper.eq(User::getAccount, userVo.getAccount());
            if (userMapper.selectOne(newUserQueryWrapper) != null) {
                return Result.error().data("msg", "Account already exists");
            }
            User user = new User();
            user.setName(userVo.getName());
            user.setGender(userVo.getGender());
            user.setAccount(userVo.getAccount());
            user.setStatus(userVo.getStatus());
            user.setRoleId(userVo.getRoleId());
            user.setClassId(userVo.getClassId());
            if (StringUtils.isNotBlank(userVo.getPassword())) {
                user.setPassword(userVo.getPassword());
            } else {
                user.setPassword(DEFAULT_PASSWORD);
            }
            userMapper.insert(user);
            return Result.ok().data("msg", "add User Success");
        }
        return Result.error().data("msg", "add user fail");
    }

    @Override
    public Result edit(String token, UserVo userVo) {
        UserVo userInfo = JwtUtils.toObj(token, UserVo.class);
        LambdaQueryWrapper<User> userQueryWrapper = new LambdaQueryWrapper<>();
        userQueryWrapper.eq(User::getAccount, userInfo.getAccount());
        if ((userMapper.selectOne(userQueryWrapper).getAccount() != null)) {
            LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.set(StringUtils.isNotBlank(userVo.getName()), User::getName, userVo.getName()).set(StringUtils.isNotBlank(userVo.getGender()), User::getGender, userVo.getGender()).set(StringUtils.isNotBlank(userVo.getAccount()), User::getAccount, userVo.getAccount()).set(StringUtils.isNotBlank(userVo.getPassword()), User::getPassword, userVo.getPassword()).set(StringUtils.isNotBlank(userVo.getRole()), User::getRoleId, userVo.getRole()).set(StringUtils.isNotBlank(userVo.getClassName()), User::getClassId, userVo.getRoleName()).set(userVo.getStatus() != null, User::getStatus, userVo.getStatus()).eq(User::getId, userVo.getId());
            userMapper.update(null, updateWrapper);
            return Result.ok().data("msg", "edit User Success");
        }
        return Result.error().data("msg", "edit user fail");
    }

    @Override
    public Result deleteUserById(Long id) {
        int i = userMapper.deleteById(id);
        return i == 1 ? Result.ok().data("msg", "成功删除") : Result.error().data("msg", "删除失败").setCode(501);
    }

    @Override
    public Result switchStatusById(Long id, Long status) {
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(User::getStatus, status).eq(User::getId, id);
        int i = userMapper.update(null, updateWrapper);
        return i == 1 ? Result.ok().data("msg", "修改成功") : Result.error().data("msg", "修改失败").setCode(501);
    }

    @Override
    public Result getUsersByRole(String role) {
        LambdaQueryWrapper<Role> queryWrapper = new LambdaQueryWrapper<>();
        Role innerRole = roleMapper.selectOne(queryWrapper.eq(Role::getRole, role));
        if (innerRole != null) {
            MPJLambdaWrapper<User> wrapper = new MPJLambdaWrapper<>();
            wrapper
                    .selectAll(User.class)
                    .eq(User::getRoleId, innerRole.getId());
            List<User> users = userMapper.selectList(wrapper);
            if (users != null && users.size() > 0) return Result.ok().data("userList", users);
            return Result.ok().data("msg", "暂无数据").setCode(404);
        }
        return Result.error().data("msg","角色不存在!");
    }

    @Override
    public Result getUserCount() {
        Long count = userMapper.selectCount(null);
        return Result.ok().data("count", count);
    }

}
